﻿Imports System.Collections
Imports System.Collections.Generic
Imports System.Xml
'Imports Jayrock.Json.Conversion
Imports Pop.Api.Parser
Imports Pop.Api.Request
Imports Pop.Api.Util

Namespace Pop.Api

    ''' <summary>
    ''' 基于REST的POP客户端。
    ''' </summary>
    Public Class DefaultPopClient
        Implements IPopClient

        Private Const m_UIN As String = "uin"
        Private Const m_TOKEN As String = "token"
        Private Const m_SPID As String = "spid"
        Private Const FORMAT_XML As String = "xml"
        Private Const SIGN As String = "sign"

        Private spid As String
        Private secretKey As String

        Private webUtils As WebUtils
        Private popLogger As IPopLogger

        WriteOnly Property SetTimeout As Integer
            Set(ByVal value As Integer)
                webUtils.Timeout = value
            End Set
        End Property
        WriteOnly Property SetPopLogger As IPopLogger
            Set(ByVal value As IPopLogger)
                popLogger = value
            End Set
        End Property

        ''' <summary>
        ''' 禁用响应结果解释
        ''' </summary>
        Property DisableParser As Boolean
        ''' <summary>
        ''' 禁用日志调试功能
        ''' </summary>
        Property DisableTrace As Boolean

#Region "DefaultPopClient Constructors"

        Sub New()
            Me.New(Nothing, Nothing)
        End Sub

        Sub New(ByVal spid As String, ByVal secretKey As String)
            Me.spid = spid
            Me.secretKey = secretKey
            Me.webUtils = New WebUtils
            Me.popLogger = New DefaultPopLogger
        End Sub

#End Region

#Region "IPopClient Members"

        Public Function Execute(Of T As PopResponse)(ByVal request As IPopRequest(Of T)) As T Implements IPopClient.Execute
            Return Execute(request, Nothing, Nothing)
        End Function

        Public Function Execute(Of T As PopResponse)(ByVal request As IPopRequest(Of T), ByVal uin As String, ByVal token As String) As T Implements IPopClient.Execute
            Return Execute(request, uin, token, DateTime.Now)
        End Function

        Public Function Execute(Of T As PopResponse)(ByVal request As IPopRequest(Of T), ByVal uin As String, ByVal token As String, ByVal timestamp As Date) As T Implements IPopClient.Execute
            Return DoExecute(request, uin, token, timestamp)
        End Function

#End Region

        Private Function DoExecute(Of T As PopResponse)(ByVal request As IPopRequest(Of T), ByVal uin As String, ByVal token As String, ByVal timestamp As Date) As T
            Try
                request.Validate()
            Catch ex As PopException
                Return createErrorResponse(Of T)(ex.ErrorCode, ex.ErrorMsg, request.Format)
            End Try

            Dim txtParams As New PopDictionary(request.GetParameters)
            txtParams.Add(m_UIN, uin)
            txtParams.Add(m_TOKEN, token)
            txtParams.Add(m_SPID, Me.spid)

            '创建sign
            Dim sign As String = txtParams.GetDictionary.GetSign(request.GetApiName, Me.secretKey)

            'Dim e As System.Text.Encoding =  System.Text.Encoding.GetEncoding(request.

            Dim body As String
            'body = webUtils.invokeApi(request, txtParams, secretKey)
            'body = webUtils.DoGet(request.ServerUrl, txtParams, sign)
            body = webUtils.DoPost(request.ServerUrl, txtParams, sign)

            ' 解释响应结果
            Dim rsp As T
            If DisableParser Then
                rsp = Activator.CreateInstance(Of T)()
                rsp.Body = body
            Else
                Dim tp As IPopParser(Of T)
                If request.Format = FORMAT_XML Then
                    tp = New PopXmlParser(Of T)
                Else
                    tp = New PopJsonParser(Of T)
                End If
                rsp = tp.Parse(body)
            End If

            ' 追踪错误的请求
            If Not DisableTrace Then
                rsp.ReqUrl = webUtils.BuildGetUrl(request.ServerUrl, txtParams)
                If rsp.IsError Then
                    popLogger.Warn(rsp.GetString & vbCrLf & rsp.Body)
                End If
            End If

            rsp.GetString = txtParams.GetString(rsp.ReqUrl, body)

            Return rsp
        End Function

        Private Shared Function createErrorResponse(Of T As PopResponse)(ByVal errCode As String, ByVal errMsg As String, ByVal format As String) As T
            Dim rsp As T = Activator.CreateInstance(Of T)()
            rsp.ErrCode = errCode
            rsp.ErrMsg = errMsg

            If format = FORMAT_XML Then
                Dim root As New XmlDocument()
                Dim bodyE As XmlElement = root.CreateElement("errorResponse")
                Dim codeE As XmlElement = root.CreateElement("errorCode")
                codeE.InnerText = errCode
                bodyE.AppendChild(codeE)
                Dim msgE As XmlElement = root.CreateElement("errorMessage")
                msgE.InnerText = errMsg
                bodyE.AppendChild(msgE)
                root.AppendChild(bodyE)
                rsp.Body = root.OuterXml
            Else
                Dim errObj As IDictionary(Of String, Object) = New Dictionary(Of String, Object)
                errObj.Add("errorCode", errCode)
                errObj.Add("errorMessage", errMsg)
                Dim root As IDictionary(Of String, Object) = New Dictionary(Of String, Object)
                root.Add("errorResponse", errObj)
                'rsp.Body = JsonConvert.ExportToString(root)
            End If

            Return rsp
        End Function

    End Class

End Namespace